//#include <utility>
//#define __NO_STD_VECTOR // Use cl::vector instead of STL version
//#include <cstdio>
//#include <cstdlib>
//#include <fstream>
//#include <iostream>
//#include <string>
//#include <iterator>
//#include <vector>
//#include <CL\cl.h>
//
//#define MAX_SOURCE_SIZE (0x100000)
//
//using namespace std;
//
//const string hw("OpenCL Hello World! \n");
//
//inline void checkErr(cl_int err, const char * name)
//{
//    if (err != CL_SUCCESS) {
//        std::cerr << "ERROR: " << name
//                 << " (" << err << ")" << std::endl;
//        exit(EXIT_FAILURE);
//    }
//}
//
//inline void dia_spmv(float* A, int rows, int diags, int* offsets, float* x, float* y) {
//  for(int row = 0; row < rows; row++) {
//    float accumulator = 0;
//    for(int diag = 0; diag < diags; diag++) {
//      int col = row + offsets[diag];
//      if ((col >= 0) && (col < rows)) {
//        accumulator += A[diag * rows + row] * x[col];
//		cout << "A[]: " << (diag*rows+row) << "col:" << col << endl;
//
//      }
//    }
//    y[row] = accumulator;
//  }
//}
//
//
//
//int main() {
//	float *arrayOne = (float*)malloc(sizeof(float)*12);
//	arrayOne[0] = 2.0;
//	arrayOne[1] = 4.0;
//	arrayOne[2] = 0.0;
//	arrayOne[3] = 0.0;
//	arrayOne[4] = 1.0;
//	arrayOne[5] = 3.0;
//	arrayOne[6] = 5.0;
//	arrayOne[7] = 7.0;
//	arrayOne[8] = 0.0;
//	arrayOne[9] = 0.0;
//	arrayOne[10] = 0.0;
//	arrayOne[11] = 6.0;
//
//	int rows = 4;
//	int diags = 3;
//
//	int *offsets = (int*)malloc(sizeof(int)*3);
//	offsets[0] = 2;
//	offsets[1] = 0;
//	offsets[2] = -3;
//
//	float *vector = (float*)malloc(sizeof(float)*4);
//	vector[0] = 1.0;
//	vector[1] = 2.0;
//	vector[2] = 3.0;
//	vector[3] = 1.0;
//	float *answer = (float*)malloc(sizeof(float)*4);
//
//	// Create the two input vectors
//    int i;
//
//	// Load the kernel source code into the array source_str
//    FILE *fp;
//    char *source_str;
//    size_t source_size;
// 
//    fp = fopen("test.cl", "r");
//    if (!fp) {
//        fprintf(stderr, "Failed to load kernel.\n");
//        exit(1);
//    }
//	source_str = (char*)malloc(MAX_SOURCE_SIZE);
//    source_size = fread( source_str, 1, MAX_SOURCE_SIZE, fp);
//    fclose( fp );
//
//	// Get platform and device information
//    cl_platform_id platform_id = NULL;
//    cl_device_id device_id = NULL;   
//    cl_uint ret_num_devices;
//    cl_uint ret_num_platforms;
//    cl_int ret = clGetPlatformIDs(1, &platform_id, &ret_num_platforms);
//    ret = clGetDeviceIDs( platform_id, CL_DEVICE_TYPE_CPU, 1, 
//            &device_id, &ret_num_devices);
//
//	// Create an OpenCL context
//    cl_context context = clCreateContext( NULL, 1, &device_id, NULL, NULL, &ret);
// 
//    // Create a command queue
//    cl_command_queue command_queue = clCreateCommandQueue(context, device_id, 0, &ret);
// 
//	// Create memory buffers on the device for each vector 
//    cl_mem array_mem_obj = clCreateBuffer(context, CL_MEM_READ_ONLY, 
//            12 * sizeof(float), NULL, &ret);
//    cl_mem rows_mem_obj = clCreateBuffer(context, CL_MEM_READ_ONLY,
//            sizeof(int), NULL, &ret);
//    cl_mem diags_mem_obj = clCreateBuffer(context, CL_MEM_READ_ONLY, 
//            sizeof(int), NULL, &ret);
//	cl_mem offsets_mem_obj = clCreateBuffer(context, CL_MEM_READ_ONLY, 
//            3*sizeof(int), NULL, &ret);
//	cl_mem vector_mem_obj = clCreateBuffer(context, CL_MEM_READ_ONLY, 
//            4*sizeof(float), NULL, &ret);
//	cl_mem answer_mem_obj = clCreateBuffer(context, CL_MEM_WRITE_ONLY, 
//            4*sizeof(float), NULL, &ret);
//
//	// Copy the lists to their respective memory buffers
//    ret = clEnqueueWriteBuffer(command_queue, array_mem_obj, CL_TRUE, 0,
//            12 * sizeof(float), &arrayOne, 0, NULL, NULL);
//    ret = clEnqueueWriteBuffer(command_queue, rows_mem_obj, CL_TRUE, 0, 
//            sizeof(int), &rows, 0, NULL, NULL);
//	ret = clEnqueueWriteBuffer(command_queue, diags_mem_obj, CL_TRUE, 0, 
//            sizeof(int), &diags, 0, NULL, NULL);
//	ret = clEnqueueWriteBuffer(command_queue, offsets_mem_obj, CL_TRUE, 0, 
//            3*sizeof(int), &offsets, 0, NULL, NULL);
//	ret = clEnqueueWriteBuffer(command_queue, vector_mem_obj, CL_TRUE, 0, 
//            4*sizeof(float), &vector, 0, NULL, NULL);
//
//
//	// Create a program from the kernel source
//    cl_program program = clCreateProgramWithSource(context, 1, 
//            (const char **)&source_str, (const size_t *)&source_size, &ret);
// 
//    // Build the program
//    ret = clBuildProgram(program, 1, &device_id, NULL, NULL, NULL);
// 
//    // Create the OpenCL kernel
//    cl_kernel kernel = clCreateKernel(program, "dia_spmv", &ret);
//
//	// Set the arguments of the kernel
//    ret = clSetKernelArg(kernel, 0, sizeof(array_mem_obj), (void *)&array_mem_obj);
//    ret = clSetKernelArg(kernel, 1, sizeof(rows_mem_obj), (void *)&rows_mem_obj);
//    ret = clSetKernelArg(kernel, 2, sizeof(diags_mem_obj), (void *)&diags_mem_obj);
//	ret = clSetKernelArg(kernel, 3, sizeof(offsets_mem_obj), (void *)&offsets_mem_obj);
//	ret = clSetKernelArg(kernel, 4, sizeof(vector_mem_obj), (void *)&vector_mem_obj);
//	ret = clSetKernelArg(kernel, 5, sizeof(answer_mem_obj), (void *)&answer_mem_obj);
// 
//    // Execute the OpenCL kernel on the list
//    size_t global_item_size = 4; // Process the entire lists
//    //size_t local_item_size = NULL; // Process one item at a time
//   // ret = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, 
//   //         &global_item_size, NULL, 0, NULL, NULL);
// 
//    // Read the memory buffer C on the device to the local variable C
// //   float *C = (float*)malloc(sizeof(float)*4);
// //   ret = clEnqueueReadBuffer(command_queue, answer_mem_obj, CL_TRUE, 0, 
// //           4 * sizeof(float), C, 0, NULL, NULL);
// //
// //   // Display the result to the screen
// //   
// //   cout << C[0] << endl;
//	//cout << C[1] << endl;
//	//cout << C[2] << endl;
//	//cout << C[3] << endl;
// 
//    // Clean up
//    ret = clFlush(command_queue);
//    ret = clFinish(command_queue);
//    ret = clReleaseKernel(kernel);
//    ret = clReleaseProgram(program);
//    ret = clReleaseMemObject(array_mem_obj);
//    ret = clReleaseMemObject(rows_mem_obj);
//    ret = clReleaseMemObject(diags_mem_obj);
//	ret = clReleaseMemObject(offsets_mem_obj);
//	ret = clReleaseMemObject(vector_mem_obj);
//	ret = clReleaseMemObject(answer_mem_obj);
//    ret = clReleaseCommandQueue(command_queue);
//    ret = clReleaseContext(context);
//
//
//
//	dia_spmv(arrayOne, rows, diags, offsets, vector, answer);
//
//	cout << answer[0] << endl;
//	cout << answer[1] << endl;
//	cout << answer[2] << endl;
//	cout << answer[3] << endl;
//
//	char myChar;
//	cin>>myChar;
//	return 0;
//}
//
//
//
